package com.atguigu.serurity.filter;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.commonutils.JwtUtil;
import com.atguigu.serurity.Util.RedisCache;
import com.atguigu.serurity.entity.LoginUser;
import io.jsonwebtoken.Claims;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

/**
 * JWT过滤器( 过滤器)=> 当用户在登录之后在每个页面之间跳转时，都会携带token(在请求后台服务器时),每次的请求都会被这个过滤器拦截进行验证
 * 包括权限校验
 */
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

	@Resource
	private RedisCache redisCache;

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
		// TODO 从请求头中获取token
		String token = request.getHeader("token");
		if (!StringUtils.hasText(token)) {
			//放行
			filterChain.doFilter(request, response);
			return;
		}
		//解析token
		String userid;
		try {
			Claims claims = JwtUtil.parseJWT(token);
			//
			userid =  claims.getSubject();

		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("token非法");
		}
		//从redis中获取用户信息
		String redisKey = "login" + userid;
		Object cacheObject = redisCache.getCacheObject(redisKey);
		/**
		 * 将json字符串转换成实体类对象
		 */
		String loginUser_jsonString = String.valueOf(cacheObject);
		LoginUser loginUser = JSONObject.parseObject(loginUser_jsonString, LoginUser.class);

		if(Objects.isNull(loginUser)){
			throw new RuntimeException("用户未登录");
		}

		//TODO 封装Authentication对象存入SecurityContextHolder

		//TODO 获取权限信息封装到Authentication中

		UsernamePasswordAuthenticationToken authenticationToken =
				new UsernamePasswordAuthenticationToken(loginUser,null,loginUser.getAuthorities());

		SecurityContextHolder.getContext().setAuthentication(authenticationToken);
		//放行
		filterChain.doFilter(request, response);
	}
}
